package com.yy.yunpan.common.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.ResponseHeaderOverrides;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 阿里云OSS工具类
 *
 * @author YY
 * @since 2025-10-01
 */
@Component
public class OssUtil {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;

    @Value("${aliyun.oss.bucket}")
    private String bucket;

    @Value("${aliyun.oss.access-key-id}")
    private String accessKeyId;

    @Value("${aliyun.oss.access-key-secret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.domain}")
    private String domain;

    /**
     * 生成PostObject上传签名
     *
     * @param userId     用户ID
     * @param fileName   文件名
     * @param fileSize   文件大小（字节）
     * @param contentType 文件类型
     * @return 签名信息
     */
    public Map<String, Object> generatePostSignature(Long userId, String fileName, Long fileSize, String contentType) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 设置上传回调URL
            String dir = "yyyunpan/" + userId + "/";

            // 生成唯一的对象键
            String objectKey = dir + UUID.randomUUID().toString() + "-" + fileName;

            // 设置上传策略
            long expireTime = 30 * 60 * 1000L; // 30分钟过期
            Date expiration = new Date(System.currentTimeMillis() + expireTime);

            PolicyConditions policyConds = new PolicyConditions();
            // 设置文件大小限制（10GB）
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 10L * 1024 * 1024 * 1024);
            // 设置上传目录
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            Map<String, Object> result = new HashMap<>();
            result.put("accessid", accessKeyId);
            result.put("policy", encodedPolicy);
            result.put("signature", postSignature);
            result.put("dir", dir);
            result.put("host", domain);
            result.put("key", objectKey);
            result.put("expire", expiration.getTime() / 1000);

            return result;
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 生成文件访问URL
     *
     * @param ossKey OSS对象键
     * @return 文件访问URL
     */
    public String getFileUrl(String ossKey) {
        return domain + "/" + ossKey;
    }

    /**
     * 删除文件
     *
     * @param ossKey OSS对象键
     */
    public void deleteFile(String ossKey) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            ossClient.deleteObject(bucket, ossKey);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 生成临时下载链接
     *
     * @param ossKey   OSS对象键
     * @param expireSeconds 过期时间（秒）
     * @return 临时下载链接
     */
    public String generateDownloadUrl(String ossKey, int expireSeconds) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            Date expiration = new Date(System.currentTimeMillis() + expireSeconds * 1000L);
            return ossClient.generatePresignedUrl(bucket, ossKey, expiration).toString();
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 生成临时下载链接（指定文件名）
     *
     * @param ossKey   OSS对象键
     * @param fileName 下载文件名
     * @param expireSeconds 过期时间（秒）
     * @return 临时下载链接
     */
    public String generateDownloadUrl(String ossKey, String fileName, int expireSeconds) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            Date expiration = new Date(System.currentTimeMillis() + expireSeconds * 1000L);

            // 创建GeneratePresignedUrlRequest对象
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, ossKey, HttpMethod.GET);
            request.setExpiration(expiration);

            // 设置响应头，指定下载文件名
            ResponseHeaderOverrides responseHeaders = new ResponseHeaderOverrides();
            responseHeaders.setContentDisposition("attachment; filename=\"" + fileName + "\"");
            request.setResponseHeaders(responseHeaders);

            return ossClient.generatePresignedUrl(request).toString();
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 生成临时预览链接
     *
     * @param ossKey   OSS对象键
     * @param expireSeconds 过期时间（秒）
     * @return 临时预览链接
     */
    public String generatePreviewUrl(String ossKey, int expireSeconds) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            Date expiration = new Date(System.currentTimeMillis() + expireSeconds * 1000L);
            // 对于预览，我们也使用预签名URL，客户端可以根据文件类型决定如何展示
            return ossClient.generatePresignedUrl(bucket, ossKey, expiration).toString();
        } finally {
            ossClient.shutdown();
        }
    }
}